package com.youzikeji.service.impl;

import com.youzikeji.dao.OrderDao;
import com.youzikeji.dao.StockDao;
import com.youzikeji.dao.UserDao;
import com.youzikeji.entity.Order;
import com.youzikeji.entity.Stock;
import com.youzikeji.entity.User;
import com.youzikeji.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private StockDao stockDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public int kill(Integer id) {
        //校验redis中秒杀商品是否还在秒杀时间内
        if (!stringRedisTemplate.hasKey("kill" + id)){
            throw new RuntimeException("当前商品抢购活动已结束！！");
        }
        //库存校验
        Stock stock = checkStock(id);
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock);
    }

    @Override
    public int kill(Integer id, Integer userId, String md5) {
//        //校验redis中秒杀商品是否还在秒杀时间内
//        if (!stringRedisTemplate.hasKey("kill" + id)){
//            throw new RuntimeException("当前商品抢购活动已结束！！");
//        }
        //验证MD5签名
        String hashKey = "KEY_" + userId + "_" + id;
        String s = stringRedisTemplate.opsForValue().get(hashKey);
        if (s == null) throw new RuntimeException("当前请求数据不合法，请稍后再试！");

        //库存校验
        Stock stock = checkStock(id);
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock);
    }

    @Override
    public String getMd5(Integer id, Integer userId) {
        //检验用户的合法性
        User user = userDao.findById(userId);
        if (user == null) throw new RuntimeException("用户不存在");
        log.info("用户信息:[{}]", user.toString());

        //检验商品的合法性
        Stock stock = stockDao.checkStock(id);
        if (stock == null) throw new RuntimeException("商品信息不存在");
        log.info("商品信息:[{}]", stock.toString());

        //生成HashKey
        String hashKey = "KEY_" + userId + "_" + id;
        //添加随机盐，随机盐一般使用工具类生成
        String key = DigestUtils.md5DigestAsHex((userId+id+"!Q*jS#").getBytes());
        stringRedisTemplate.opsForValue().set(hashKey, key, 120, TimeUnit.SECONDS);
        log.info("Redis写入: [{}] [{}]", hashKey, key);
        return key;
    }

    //库存校验
    private Stock checkStock(Integer id){
        //根据商品id校验库存
        Stock stock = stockDao.checkStock(id);
        //已售与原始库存相同，没货了
        if (stock.getCount().equals(stock.getSale())){
            throw new RuntimeException("库存不足！！");
        }
        return stock;
    }

    //扣除库存
    private void updateSale(Stock stock){
        //sql层面完成销量+1和版本号+1
        //持久化
        int updateRows = stockDao.updateSale(stock);
        //数据表中的行数据没有更新
        if (updateRows == 0) {
            throw new RuntimeException("抢购失败，请重试！！");
        }
    }

    //创建订单
    private Integer createOrder(Stock stock){
        //创建订单
        Order order = new Order();
        //链式编程，设置订单的商品id、名称、订单创建时间
        order.setSid(stock.getId()).setName(stock.getName()).setCreateDate(new Date());
        orderDao.createOrder(order);
        return order.getId();
    }
}
